#include "control.h"

    Control* Control::pinstance = 0;// initialize pointer
  Control* Control::Instance ()
  {
    if (pinstance == 0)  // is it the first call?
    {
      pinstance = new Control; // create sole instance
    }
    return pinstance; // address of sole instance
  }
  Control::Control()
  {
    std::cout << "constructing control\n";
    //notebook = new Gtk::Notebook();
    consoleSize = 100;
    notebook.set_show_tabs(false);
    Shelf_consoleView = new WebWidget();
    Shelf_consoleView->hookConsoleFunctions();

    //Shelf_webView = new WebWidget();
    //mainwindow = new MainWindow;
    //mainwindow->addConsole(Shelf_consoleView->getWidget());
    //Shelf_consoleView->open("http://www.google.com/ig");
    //newShelf("http://www.google.com/ig");
    //webviews.push_back(Shelf_webView);

    commands.push_back(shelfCommand("setsize", "setsize <size>(small, big or huge)"));
    commands.push_back(shelfCommand("hide", "hide the console view"));
    commands.push_back(shelfCommand("ls", "list open shelves"));
    commands.push_back(shelfCommand("close", "close current shelf"));
    commands.push_back(shelfCommand("new", "open new shelf"));
    commands.push_back(shelfCommand("search", "search <keyword(s)> use your favorite search engine"));
    commands.push_back(shelfCommand("quit", "close all shelves and shut down"));
    commands.push_back(shelfCommand("back", "go back..."));
    commands.push_back(shelfCommand("forward", "go forward..."));
    commands.push_back(shelfCommand("reload", "reload page"));
    commands.push_back(shelfCommand("info", "get information about the current page"));
  }

int Control::getCurrentShelf()
{
    return (notebook.get_current_page());
}

void Control::newShelf(std::string uri, bool internal)
{
    std::cout << "opening new shelf for " << uri << "\n\n";
    webviews.push_back(new WebWidget());

    windows.push_back(new Gtk::ScrolledWindow());
    windows.back()->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
    windows.back()->add(*(webviews.back()->getWidget()));
    int newpage = notebook.append_page(*(windows.back()));//, "shelf");
    if(internal)
    {
        webviews.back()->html(uri);
    }
    else
    {
        webviews.back()->open(uri);
    }
    notebook.show_all_children();
    notebook.set_current_page(newpage);

}

void Control::plug(std::string command)
{
    plugins.push_back(new Plugin(command));
    windows.push_back(new Gtk::ScrolledWindow());
    windows.back()->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
    windows.back()->add(*(plugins.back()->webView->getWidget()));
    int newpage = notebook.append_page(*(windows.back()));//, "shelf");
    notebook.show_all_children();
    notebook.set_current_page(newpage);
}

Plugin* Control::getPluginByName(std::string name)
{
    for(unsigned int i = 0; i< plugins.size(); i++)
    {
        if(plugins[i]->name == name)
            return plugins[i];
    }
    return 0;
}
bool Control::pluginUpdater()
{
    for(unsigned int i = 0; i < plugins.size(); i++)
    {
        plugins[i]->update();
    }
    return true;
}
void Control::addNotification(std::string icon, std::string hover, std::string jscript)
{
    //careful here, jscript cannot contain single quotes ('), must be escaped double quotes (\")
    std::stringstream notification;
    notification << "addNotification(\"<a href='javascript:" << jscript << "' onmouseout='javascript:statusPrint(\"+'\"\"'+\")' onmouseover='javascript:statusPrint(\" + '\"" << hover << "\"' + \");' ><img src='" << icon << "'></a>\");";
    std::cout << "NOTIFY: " << notification.str() << "\n";
    Shelf_consoleView->script(notification.str());
}

WebWidget* Control::getActiveWebWidget()
{
    int widgetindex = notebook.get_current_page();
    return webviews[widgetindex];
}
WebWidget* Control::getWebWidgetByJSContext(JSContextRef ctx)
{
    for(int i=0;i<webviews.size();i++)
    {
        if(webviews[i]->getJavascriptContext() == ctx)
        {
            std::cout << "ctx hit on " << i << "\n";
            return webviews[i];
        }
    }
    return webviews[0];
}

WebWidget* Control::getWebWidgetByView(WebKitWebView* webView)
{
    for(int i=0;i<webviews.size();++i)
    {
        if(webView == webviews[i]->getWebView())
        {
            std::cout << "hit on "<< i << "\n";
            return webviews[i];
        }
    }
    return webviews[0];
}

int Control::getIdByView(WebKitWebView* webView)
{
    for(int i=0;i<webviews.size();++i)
    {
        if(webView == webviews[i]->getWebView())
        {
            std::cout << "hit on "<< i << "\n";
            return i;
        }
    }
    return 0;
}

std::string Control::getNameFromURI(std::string uri)
{
    if(uri[uri.size()-1] == '/') return uri.substr(0,uri.size() -1);
    return uri;//escapeName(uri);

    //boost::smatch matches;
    //boost::regex e("(shelf|file|http|https):/+(.*?)/");
    //uri += '/'; //dirty hack to make sure regex doesn't fail for simple url's
    //if(boost::regex_search(uri, matches,e))
    //{
      //  uri = uri.substr(0,uri.size() -1);
      //  std::cout << matches[1] << "\n";
       // std::cout << matches[2] << "\n";
      //  if(matches[1] == "file")
        //{
            //return filename
          //  return uri.substr(uri.rfind("/") + 1);
       // }
       // else
        //{
          //  return std::string(matches[2]);
            /*
            if(rindex != lindex)
            {
                //return stripped uri base (two dots in url)
                int length = std::string(matches[2]).size() - lindex - (std::string(matches[2]).size() - rindex) -1;
                return (std::string(matches[2]).substr(lindex+1, length));
            }
            else
            {
                //return stripped uri base (one dot in url)
                int length = std::string(matches[2]).size() - rindex;
                return (std::string(matches[2]).substr(0, length));
            }*/
            /*
        }
    }
    else
    {
        //no known protocol found in uri, don't know how to identify this
        return "unknown";
    }
    //this one is never reached*/
    return "unknown";

}

std::string Control::escapeName(std::string name)
{
    for(unsigned int i=0; i < name.size(); i++)
    {
        if(name[i] == ':') name[i] = 95;
        if(name[i] == '/') name[i] = 95;
        if(name[i] == '.') name[i] = 95;
    }
    return name;
}

std::string Control::getFavicon(std::string url)
{
    if(url.substr(0,6) == "file:/") return "diskicon.png";
// TODO (armen#1#): remove boost dependency for regex
    boost::smatch matches;


    std::string filename = "favicon.ico";
    std::string baseURL = Control::Instance()->getNameFromURI(url);
    int index = baseURL.find("/", 7);
    if(index != std::string::npos)
    {
        baseURL = baseURL.substr(0, index);
    }
    baseURL += "/favicon.ico";
    //baseURL = "http://"+ baseURL;
    std::cout << "\ngetting favicon at "<<baseURL<<" and saving it to "<<filename<<"\n";
    FILE *icofile = fopen(filename.c_str(), "w");
    CURL *curlhandle = curl_easy_init();
    curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, icofile);
    curl_easy_setopt(curlhandle, CURLOPT_URL, baseURL.c_str());
    int favOK = curl_easy_perform(curlhandle);
    curl_easy_cleanup(curlhandle);
    fclose(icofile);
    if(favOK == 0)
    {

        //boost::regex e("(file|http|https):/+(.*?)/");
        //if(boost::regex_search(url, matches,e))
        std::string name = escapeName(url);


// TODO (armen#1#): don't use imagemagick, read ico file format instead            std::string outfile = std::string("convert favicon.ico ")+ name + ".png";
            system(outfile.c_str());
            std::string copyifneeded = "cp ";
            copyifneeded += name + "-0.png ";
            copyifneeded += name + ".png";
            system(copyifneeded.c_str()); //nasty hack in case convert outputs multiple layers
            return std::string(name) + ".png";

    }
    return "default.png";
}
